#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <time.h>

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

float maximum(float a[5])
{
	float max=a[0];
	for(int i=1;i<5;i++)
	{
		if(a[i]>max)
			max=a[i];
	}
	return max;
}
float minimum(float a[5])
{
	float min=a[0];
	for(int i=1;i<5;i++)
	{
		if(a[i]<min)
			min=a[i];
	}
	return min;
}
float average(float a[5])
{
	float mean=0.0;
	for(int i=0;i<5;i++)
		mean+=(a[i]/5);
	return mean;
}
float Average(vector<float> v)
{ 
	float sum=0;
		if(v.size()==0) return 0;
		else
		{
			for(int i=0;i<v.size();i++)
               sum+=v[i];
           return sum/v.size();
		}
}
float deviation(vector<float> v)
{
	float E=0;
	float ave=Average(v);
	if(v.size()==0) return 0;
	else
	{
    for(int i=0;i<v.size();i++)
            E+=(v[i] - ave)*(v[i] - ave);
    return sqrt(E/v.size());
	}
}
float spreads(float a[5])
{
	float mean=average(a);
	
	vector<float> ab,be;

	for(int i=0;i<5;i++)
		if(a[i]<mean)
			ab.push_back(a[i]);
		else
			be.push_back(a[i]);

	float std_ab=0,std_be=0;
	std_ab=deviation(ab);
	std_be=deviation(be);

	return(abs(std_ab-std_be));
}

int main(int, char** argv)
{
	//////////////////////////////////////////////////////////////// Variable Declaration //////////////////////////////////////////////////////////

	VideoCapture cap(argv[1]); // open the file
    if(!cap.isOpened())  // check if we succeeded
        return -1;

	int no_frames=0;
	Size image_size((int)cap.get(CV_CAP_PROP_FRAME_WIDTH),(int)cap.get(CV_CAP_PROP_FRAME_HEIGHT));
	Mat frame=Mat::zeros(image_size,CV_8UC1);
	Mat cur_temp=Mat::zeros(image_size,CV_8UC1);
	Mat prev_temp=Mat::zeros(image_size,CV_8UC1);
   	Mat next_temp=Mat::zeros(image_size,CV_8UC1);
	Mat prev_temp2=Mat::zeros(image_size,CV_8UC1);
	Mat next_temp2=Mat::zeros(image_size,CV_8UC1);
	Mat background = Mat::zeros(image_size,CV_8UC1);
	Mat range = Mat::zeros(image_size,CV_8UC1);
    Mat spreadsymm = Mat::zeros(image_size,CV_8UC1);

	uchar* data_range=(uchar*)range.data;
	uchar* data_cur=(uchar*)cur_temp.data;
	uchar* data_prev=(uchar*)prev_temp.data;
	uchar* data_prev2=(uchar*)prev_temp2.data;
	uchar* data_next=(uchar*)next_temp.data;
	uchar* data_next2=(uchar*)next_temp2.data;
	uchar* data_spreadsymm = (uchar*)spreadsymm.data;
	int width_step=cur_temp.step1();
	float max,min;	
	float a[5]={0.0,0.0,0.0,0.0,0.0},ss=0.0,rangex=0.0;

	/////////////////////////////////////////////////////////// Setting Files //////////////////////////////////////////////////////////////////

	ofstream range_file,ss_file;

	range_file.open("range.txt",ios::out);
	ss_file.open("ss.txt",ios::out);

	if(range_file.is_open() && ss_file.is_open())
	{
        cout<<"\nFiles open.\n";
	}
	else	
		cout<<"\nUnable to open the file.\n";
	

	/////////////////////////////////////////////////////////// video reading ////////////////////////////////////////////////////////////////////////////////

	for( ; ; )
    {		
        cap>>frame; 
		if(frame.empty()){exit(0);}

		no_frames++;		
        cvtColor(frame, next_temp2, CV_BGR2GRAY);
		imshow("current video", next_temp2); 
			
		//////////////////////////////////////////////////// Feature Extraction ////////////////////////////////////////////////
  
		/**************************************** Range ****************************************/
   
	if(no_frames>=5)
	{
	   for(int i=0;i<image_size.height;i++)
		{
			for(int j=0;j<image_size.width;j++)
			{
				a[0]=data_prev2[i*width_step+j];
				a[1]=data_prev[i*width_step+j];
				a[2]=data_cur[i*width_step+j];
				a[3]=data_next[i*width_step+j];
				a[4]=data_next2[i*width_step+j];

				max= maximum(a);
				min= minimum(a);	
				rangex=max-min;
				range_file<<rangex<<endl;

				ss=spreads(a);
				ss_file<<ss<<endl;

				data_spreadsymm[i*width_step+j]=ss;
				data_range[i*width_step+j]=rangex;        
			}			
		}
	 }

	   //imshow("Range",range);
	   //imshow("Spreadsymmetry",spreadsymm);

		//////////////////////////////////////////////////////////////////////////// Frame Copying ///////////////////////////////////////////////////////////////////////

		prev_temp.copyTo(prev_temp2);
        cur_temp.copyTo(prev_temp);
        next_temp.copyTo(cur_temp);
		next_temp2.copyTo(next_temp);

		if(waitKey(50) >= 0)
		{
			break;
		}
	}

	cout<<"No of frames for training video:"<<no_frames<<endl;
	range_file.close();	
	ss_file.close();
	waitKey(0);
	destroyAllWindows();
	cap.release();
}